package com.cmwa.scbp.sys.permission.authority.service.impl;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.velocity.VelocityContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import com.cmwa.scbp.base.constants.Constant;
import com.cmwa.scbp.base.mvc.entity.Employee;
import com.cmwa.scbp.base.mvc.service.impl.BatchOperServiceImpl;
import com.cmwa.scbp.sys.msg.adapter.EmailMessageTemplate;
import com.cmwa.scbp.sys.msg.adapter.impl.AutoOperationMessageByVelocityImpl;
import com.cmwa.scbp.sys.msg.vo.ManualOperationParamsVo;
import com.cmwa.scbp.sys.msg.vo.OperationResultVo;
import com.cmwa.scbp.sys.permission.authority.dao.AuthorityDao;
import com.cmwa.scbp.sys.permission.authority.entity.AuthorityVo;
import com.cmwa.scbp.sys.permission.authority.service.AuthorityService;
import com.cmwa.scbp.sys.permission.dataAuthority.entity.AuthorityEnum;
import com.cmwa.scbp.sys.permission.post.dao.PostDao;
import com.cmwa.scbp.sys.permission.post.entity.PostVo;
import com.cmwa.scbp.sys.permission.privilege.dao.PrivilegeDao;
import com.cmwa.scbp.utils.SessionUtils;
import com.cmwa.scbp.utils.cached.DepartmentCached;
import com.cmwa.scbp.utils.cached.DictionaryCached;
import com.cmwa.scbp.utils.cached.EmployeeCached;
import com.cmwa.scbp.utils.spring.SpringContextUtil;

@Service
public class AuthorityServiceImpl extends BatchOperServiceImpl implements AuthorityService{
	
	private static Logger log = LoggerFactory.getLogger(AuthorityServiceImpl.class);
	
	@Resource
	private AuthorityDao authorityDao;
	@Resource
	private PostDao postDao;
	
	@Resource(name = "asyncExecutor")
	private ThreadPoolTaskExecutor threadPoolTaskExecutor;
	@Resource
	private PrivilegeDao privilegeDao;

	/**
	 * 根据传参查询对应的数据角色并赋权(单个)
	 *  
	 * @param authorityVo
	 * @throws Exception 
	 */
	@Override
	public void addAuthority(AuthorityVo authorityVo) throws Exception {
		if (authorityVo == null || StringUtils.isBlank(authorityVo.getRoleType())) {
			return;
		}
		String roleType = DictionaryCached.getDictName("ROLE_XXX_TYPE", authorityVo.getRoleType());
		
		log.error("=== AuthorityServiceImpl -> addAuthority: 开始添加权限(" + roleType + ")， " + authorityVo);
		long start = System.currentTimeMillis();
		// 查询岗位、部门、营销经理的数据角色集合
		List<AuthorityVo> authorityList = this.queryauthorityList(authorityVo, "add");
		// 查询分享角色
		List<AuthorityVo> shareAuthority = this.queryShareAuthority(authorityList);
		authorityList.addAll(shareAuthority);
		// 保存角色与数据的关联关系
		saveAuthority(authorityList);
		long end = System.currentTimeMillis();
		log.error("=== AuthorityServiceImpl -> addAuthority: 赋权结束(" + roleType + ")，耗时: " + (end- start) + "ms");
	}
	
	/**
	 * 根据传参查询对应的数据角色并赋权(批量)
	 *  
	 * @param authorityVo
	 * @throws Exception 
	 */
	@Override
	public void addAuthority(List<AuthorityVo> authorityVoList) throws Exception {
		if (CollectionUtils.isNotEmpty(authorityVoList) && authorityVoList.size() > 0) {
			log.error("=== AuthorityServiceImpl -> addAuthority: 开始批量添加权限， " + authorityVoList);
			long start = System.currentTimeMillis();
			List<AuthorityVo> authorityList = new ArrayList<AuthorityVo>();
			for (AuthorityVo authorityVo : authorityVoList) {
				// 查询岗位、部门、营销经理的数据角色集合
				authorityList.addAll(this.queryauthorityList(authorityVo, "add"));
			}
			// 去重
			List<AuthorityVo> listDistinct = listDistinct(authorityList);
			// 查询分享角色
			List<AuthorityVo> shareAuthority = this.queryShareAuthority(listDistinct);
			authorityList.addAll(shareAuthority);
			// 去重
			listDistinct = listDistinct(authorityList);
			// 保存角色与数据的关联关系
			saveAuthority(listDistinct);
			long end = System.currentTimeMillis();
			log.error("=== AuthorityServiceImpl -> addAuthority: 批量赋权结束，耗时: " + (end- start) + "ms");
		}
	}
	
	/**
	 * 根据传参查询对应的数据角色并清除权限(单个)
	 *  
	 * @param authorityVo
	 * @throws Exception 
	 */
	@Override
	public void cleanUpAuthority(AuthorityVo authorityVo) throws Exception {
		if (authorityVo == null || StringUtils.isBlank(authorityVo.getRoleType())) {
			return;
		}
		String roleType = DictionaryCached.getDictName("ROLE_XXX_TYPE", authorityVo.getRoleType());
		
		log.error("=== AuthorityServiceImpl -> cleanUpAuthority: 开始清除权限(" + roleType + ")， " + authorityVo);
		long start = System.currentTimeMillis();
		// 查询岗位、部门、营销经理的数据角色集合
		List<AuthorityVo> authorityList = this.queryauthorityList(authorityVo, "del");
		// 查询分享角色
		List<AuthorityVo> shareAuthority = this.queryShareAuthority(authorityList);
		authorityList.addAll(shareAuthority);
		// 清除对应数据与角色关联关系
		updateAuthorityStat(listDistinct(authorityList));
		long end = System.currentTimeMillis();
		log.error("=== AuthorityServiceImpl -> addAuthority: 清除权限结束(" + roleType + ")，耗时: " + (end- start) + "ms");
	}
	
	/**
	 * 根据传参查询对应的数据角色并清除权限(批量)
	 *  
	 * @param authorityVo
	 * @throws Exception 
	 */
	public void cleanUpAuthority(List<AuthorityVo> authorityVoList) throws Exception {
		if (CollectionUtils.isNotEmpty(authorityVoList) && authorityVoList.size() > 0) {
			log.error("=== AuthorityServiceImpl -> cleanUpAuthority: 开始批量清除权限， " + authorityVoList);
			long start = System.currentTimeMillis();
			List<AuthorityVo> authorityList = new ArrayList<AuthorityVo>();
			for (AuthorityVo authorityVo : authorityVoList) {
				authorityList.addAll(this.queryauthorityList(authorityVo, "del"));
			}
			// 去重
			List<AuthorityVo> listDistinct = listDistinct(authorityList);
			// 查询分享角色
			List<AuthorityVo> shareAuthority = this.queryShareAuthority(listDistinct);
			authorityList.addAll(shareAuthority);
			// 去重
			listDistinct = listDistinct(authorityList);
			// 清除对应数据与角色关联关系
			updateAuthorityStat(listDistinct);
			long end = System.currentTimeMillis();
			log.error("=== AuthorityServiceImpl -> addAuthority: 批量清除权限结束，耗时: " + (end- start) + "ms");
		}
	}
	
	/**
	 * 查询数据角色
	 */
	private List<AuthorityVo> queryauthorityList(AuthorityVo authorityVo, String type) {
		List<AuthorityVo> authorityList = new ArrayList<AuthorityVo>();
		if (authorityVo == null) {
			return authorityList;
		}
		
		String resourceName = getResourceName(authorityVo);
		String roleType = DictionaryCached.getDictName("ROLE_XXX_TYPE", authorityVo.getRoleType());
		
		PostVo postVo = new PostVo();
		postVo.setPostCode(authorityVo.getPostCode());
		// 根据岗位代码查询对应岗位信息
		postVo = postDao.queryPostInfo(postVo);
		
		if (AuthorityEnum.DEPT == authorityVo.getEmpowermentWay()) {
			/** 
			 * 根据部门 + 默认部门为“是”查询数据角色
			 */
			List<AuthorityVo> deptAuthorityList = authorityDao.queryAuthorityListByDept(authorityVo);
			if ((CollectionUtils.isEmpty(deptAuthorityList) || deptAuthorityList.size() <= 0) && StringUtils.equals("add", type)) {
				// 若根据部门查询不到对应的数据角色，则发送通知
				this.sendNotice(resourceName, "部门：" + DepartmentCached.getName(authorityVo.getOrgId()) + "，数据角色类型：" + roleType + "，");
			} else {
				authorityList.addAll(deptAuthorityList);
			}
		} else if (AuthorityEnum.EMP_POST == authorityVo.getEmpowermentWay()) {
			/** 
			 * 根据人员 + 岗位code查询数据角色
			 */
			// 如果岗位可以赋权
			if (postVo != null && StringUtils.equals(postVo.getIsAuth(), Constant.C_STATUS_Y) && StringUtils.isNotBlank(authorityVo.getEmpId())) {
				
				String[] empIds = authorityVo.getEmpId().split(",");
				/**
				 *  循环人员分别进行查询数据角色
				 *  不放在一起查询，是因为一起查询无法判断有没有某个人员没有查出对应的数据角色，
				 *  因而无法发送对应的通知
				 */
				for (String empId : empIds) {
					AuthorityVo vo = new AuthorityVo();
					vo.setEmpId(empId);
					vo.setPostCode(authorityVo.getPostCode());
					vo.setRoleType(authorityVo.getRoleType());
					vo.setResourceId(authorityVo.getResourceId());
					vo.setResourceType(authorityVo.getResourceType());
					
					List<AuthorityVo> postAuthorityList = authorityDao.queryAuthorityListByEmpAndPost(vo);
					
					// 若找不到数据角色集合，则发送通知
					if ((CollectionUtils.isEmpty(postAuthorityList) || postAuthorityList.size() <= 0) && StringUtils.equals("add", type)) {
						this.sendNotice(resourceName, "人员：" + EmployeeCached.getName(empId) + "，数据角色类型：" + roleType + "，岗位：" + postVo.getPostTitle() + "，");
					} else {
						authorityList.addAll(postAuthorityList);
					}
				}
			}
		}  else if (AuthorityEnum.DEPT_POST == authorityVo.getEmpowermentWay()) {
			/**
			 *  根据部门 + 岗位code查询数据角色
			 */
			// 如果岗位可以赋权
			if (postVo != null && StringUtils.equals(postVo.getIsAuth(), Constant.C_STATUS_Y)) {
				List<AuthorityVo> authorityListByDeptAndPost = authorityDao.queryAuthorityListByDeptAndPost(authorityVo);
				
				// 若查询不到数据角色集合，则发送通知  通过(一对多通道)郭一楠-部门营销经理岗未找到对应的数据角色，无法进行赋权
				if ((CollectionUtils.isEmpty(authorityListByDeptAndPost) || authorityListByDeptAndPost.size() <= 0) && StringUtils.equals("add", type)) {
					postVo.setPostCode(DictionaryCached.getDictName("POST_CODE", "BMYXJL"));
					// 根据岗位代码查询对应岗位信息
					postVo = postDao.queryPostInfo(postVo);
					if(postVo != null) {
						this.sendNotice(resourceName, "部门：" + DepartmentCached.getName(authorityVo.getOrgId()) + "，数据角色类型：" + roleType + "，岗位：" + postVo.getPostTitle() + "，");
					}
				} else {
					authorityList.addAll(authorityListByDeptAndPost);
				}
			}
		}  else if (AuthorityEnum.POST == authorityVo.getEmpowermentWay()) {
			/**
			 *  根据岗位code查询数据角色
			 */
			// 如果岗位可以赋权
			if (postVo != null && StringUtils.equals(postVo.getIsAuth(), Constant.C_STATUS_Y)) {
				List<AuthorityVo> authorityListByPost = authorityDao.queryAuthorityListByPost(authorityVo);
				
				// 若查询不到数据角色集合，则发送通知  通过(一对多通道)郭一楠-部门营销经理岗未找到对应的数据角色，无法进行赋权
				if ((CollectionUtils.isEmpty(authorityListByPost) || authorityListByPost.size() <= 0) && StringUtils.equals("add", type)) {
					postVo.setPostCode(DictionaryCached.getDictName("POST_CODE", "GSYXJL"));
					// 根据岗位代码查询对应岗位信息
					postVo = postDao.queryPostInfo(postVo);
					this.sendNotice(resourceName, "岗位：" + postVo.getPostTitle() + "，数据角色类型:" + roleType + "，");
				} else {
					authorityList.addAll(authorityListByPost);
				}
			}
		} 
		return authorityList;
	}
	
	/**
	 * 查询分享角色
	 * @param authorityList 
	 * @param type
	 */
	private List<AuthorityVo> queryShareAuthority(List<AuthorityVo> authorityList) {
		log.error("=== AuthorityServiceImpl -> queryShareAuthority: 开始查询分享角色的数据角色集合");
		long start = System.currentTimeMillis();
		List<AuthorityVo> authorityShareList = new ArrayList<AuthorityVo>();
		// 循环查询分享的数据角色集合
		for (int i = 0; i < authorityList.size(); i++) {
			// 获取分享角色集合
			authorityShareList.addAll(getshareList(authorityList.get(i)));
		}
		long end = System.currentTimeMillis();
		log.error("=== AuthorityServiceImpl -> queryShareAuthority: 开始查询分享角色的数据角色集合, 耗时：" + (end - start) + "ms");
		return authorityShareList;
	}
	
	/**
	 *  查询分享角色集合
	 * @param authorityVo
	 * @return
	 */
	private List<AuthorityVo> getshareList(AuthorityVo authorityVo) {
		AuthorityVo authority = new AuthorityVo();
		String roleId = authorityVo.getRoleId();
		authority.setRoleId(roleId);
		// 权限类型（1:普通）
		authority.setAuthorityType(Constant.AUTHORITY_TYPE1);
		authority.setRoleType(authorityVo.getRoleType());
		authority.setResourceId(authorityVo.getResourceId());
		authority.setResourceType(authorityVo.getResourceType());
		
		return authorityDao.queryAuthorityShareList(authority);
	}
	
	/** 
	 * 更新关联关系表状态(物理删除)
	 * @param authorityVo
	 * @param type
	 * @throws Exception 
	 */
	private void updateAuthorityStat(List<AuthorityVo> authorityList) throws Exception {
		String roleId = null;
		
		List<AuthorityVo> resourceRelationsList = new ArrayList<AuthorityVo>(); // 资源-角色关联关系表数据
		List<AuthorityVo> resourceLimitList = new ArrayList<AuthorityVo>();  // 资源-人员关联关系表数据
		
		if (CollectionUtils.isNotEmpty(authorityList) && authorityList.size() > 0) {
			for (int i = 0; i < authorityList.size(); i++) {
				roleId = authorityList.get(i).getRoleId();
				AuthorityVo auth = new AuthorityVo();
				auth.setRoleId(roleId);
				
				if (StringUtils.isNotBlank(authorityList.get(i).getResourceId())) {
					auth.setResourceId(authorityList.get(i).getResourceId());
					auth.setResourceType(authorityList.get(i).getResourceType());
					resourceRelationsList.add(auth);
					resourceLimitList.add(auth);
				}
			}
			// 删除资源-角色关联关系表数据
			if (CollectionUtils.isNotEmpty(resourceRelationsList) && resourceRelationsList.size() > 0) {
				batchOperateData("com.cmwa.scbp.sys.permission.authority.dao.AuthorityDao.deleteRoleResourceInfo", listDistinct(resourceRelationsList), 50);
			}
			
			// 删除资源-人员关联关系表数据
			if (CollectionUtils.isNotEmpty(resourceLimitList) && resourceLimitList.size() > 0) {
				batchOperateData("com.cmwa.scbp.sys.permission.privilege.dao.PrivilegeDao.deleteResourceLimitById", resourceLimitList, 50);
			}
		}
	}
	
	
	/**
	 * 保存角色与数据的关联关系
	 * @param authorityList 角色集合
	 * @throws Exception 
	 */
	private void saveAuthority(List<AuthorityVo> authorityList) throws Exception {
		Employee employee = SessionUtils.getEmployee();
		String roleId = null;
		
		List<AuthorityVo> resourceRelationsList = new ArrayList<AuthorityVo>(); //资源-角色关联关系表数据
		List<AuthorityVo> resourceLimitList = new ArrayList<AuthorityVo>(); //资源-人员关联关系表数据
		
		if (CollectionUtils.isNotEmpty(authorityList) && authorityList.size() > 0) {
			for (int i = 0; i < authorityList.size(); i++) {
				roleId = authorityList.get(i).getRoleId();
				AuthorityVo auth = new AuthorityVo();
				auth.setRoleId(roleId);
				auth.setStatus(Constant.C_STATUS_C);
				auth.setCreateId(employee.getID() == null ? "system" : employee.getID());
				
				if (StringUtils.isNotBlank(authorityList.get(i).getResourceId())) {
					auth.setResourceId(authorityList.get(i).getResourceId());
					auth.setResourceType(authorityList.get(i).getResourceType());
					// 循环角色查询角色项目关系表有没有数据
					int count = authorityDao.countRoleResourceInfo(auth);
					// 如果没有就添加
					if (count == 0) {
						resourceRelationsList.add(auth);
					}
					resourceLimitList.add(auth);
				}
			}
			// 新增资源-角色关联关系表数据
			if (CollectionUtils.isNotEmpty(resourceRelationsList) && resourceRelationsList.size() > 0) {
				batchOperateData("com.cmwa.scbp.sys.permission.authority.dao.AuthorityDao.addRoleResourceInfo", listDistinct(resourceRelationsList), 50);
			}
			// 新增资源-人员关联关系表数据
			if (CollectionUtils.isNotEmpty(resourceLimitList) && resourceLimitList.size() > 0) {
				batchOperateData("com.cmwa.scbp.sys.permission.privilege.dao.PrivilegeDao.batchInsertResourceId", resourceLimitList, 50);
			}
		}
	}

	/**
	 * 去重
	 * @param list
	 * @return
	 */
	private List<AuthorityVo> listDistinct(List<AuthorityVo> list) {
		List<AuthorityVo> authorityList = new ArrayList<AuthorityVo>();
		if (CollectionUtils.isEmpty(list) || list.size() <= 0) {
			return authorityList;
		}
		
		for (AuthorityVo authorityVo : list) {
			String oldResourceId = "";
			String oldRoleId = authorityVo.getRoleId();
			
			if (StringUtils.isNotBlank(authorityVo.getResourceId())) {
				oldResourceId = authorityVo.getResourceId();
			}
			
			boolean exists = false;
			for (AuthorityVo vo : authorityList) {
				String newResourceId = "";
				String newRoleId = vo.getRoleId();
				
				if (StringUtils.isNotBlank(vo.getResourceId())) {
					newResourceId = vo.getResourceId();
				}
				
				if (StringUtils.equals(oldResourceId, newResourceId) && StringUtils.equals(oldRoleId, newRoleId)) {
					exists = true;
				}
			}
			if (!exists) {
				authorityList.add(authorityVo);
			}
		}
		return authorityList;
	}
	
	/**
	 * 数据权限赋权失败通知
	 * @param authorityVo
	 */
	private void sendNotice(final String resourceName, final String way) {
		if (StringUtils.isNotBlank(resourceName) && StringUtils.isNotBlank(way)) {
			threadPoolTaskExecutor.execute(new Runnable() {
				@Override
				public void run() {
					ManualOperationParamsVo params = new ManualOperationParamsVo();
					EmailMessageTemplate operation = (EmailMessageTemplate)SpringContextUtil.getBean(AutoOperationMessageByVelocityImpl.class);
					params.setEmpId(SessionUtils.getEmployee().getID()); // 创建人
					VelocityContext dataSource = new VelocityContext();
					dataSource.put("resourceName", resourceName);
					dataSource.put("way", way);
					params.setDataSource(dataSource);
					params.setMsgCode(ManualOperationParamsVo.SUBTYPE_QXTZ001);//小类型
					params.setSendTime(ManualOperationParamsVo.SENDTIME_NOW);//发送时间
					params.setSendTimeAsyn(ManualOperationParamsVo.SENDTIME_NOW_ASYN);
					try {
						OperationResultVo rst = operation.execute(params);
						log.error(rst.getResultContent());
					} catch (Exception e) {
						log.error(e.toString());
						e.printStackTrace();
					}
				}
			});
		}
	}
	
	/**
	 * 查询资源名称
	 * @param authorityVo
	 * @return
	 */
	private String getResourceName(AuthorityVo authorityVo) {
		String resourceName = "";
		return resourceName;
	}
	
}
